#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <./cpu.h>
#include <string.h>
#include "./rdtsc.h"

// #define DEBUG

pid_t pid;
unsigned long long begin_tick, end_tick;
unsigned long long curr_CPU_freq;

void main()
{
  curr_CPU_freq = get_current_CPU_freq();  
  char buf;
  char *msg1 = "parent"; 

  // create two pipes; One from parent to child; One from child to parent
  // pipe[0] read; pipe[1] write;
  #ifdef DEBUG
  fprintf(stderr, "Creating two pipes...\n");
  #endif
  int pipe_ptc[2];
  int pipe_ctp[2];
  if(pipe(pipe_ptc) == -1)
  {
    perror("pipe_ptc");
    exit(1);
  } 
  if(pipe(pipe_ctp) == -1)
  {
    perror("pipe_ctp");
    exit(1);
  }
  
  // create child process
  pid = fork();
  if(pid == -1)
  {
    perror("Creating child process");
    exit(1);
  }

  if(pid == 0)
  {
    // Child Process
    char *msg2 = "child";
    // start timer
    begin_tick = rdtsc();
    #ifdef DEBUG
    fprintf(stderr, "Begin tick is %llu\n", begin_tick);
    fflush(stderr);
    #endif
 
    // send 1-word msg to parent
    #ifdef DEBUG
    fprintf(stderr, "Child sending...\n");
    fflush(stderr);
    #endif
    // close unused read end
    close(pipe_ctp[0]);
    write(pipe_ctp[1], msg2, 4);
    // close write after msg sending
    close(pipe_ctp[1]);

    // wait to receive msg from parent

    // read from pipe from parent
    // close unused wrtie end
    #ifdef DEBUG
    fprintf(stderr, "Child Reading...\n");
    fflush(stderr);
    #endif
    close(pipe_ptc[1]);
    while(read(pipe_ptc[0], &buf, 1) > 0)
    {
      // write message to stderr
      #ifdef DEBUG
      fprintf(stderr, "%c", buf);
      fflush(stderr);
      #endif
    }
    #ifdef DEBUG
    fprintf(stderr, "\n");
    fflush(stderr);
    #endif
    close(pipe_ptc[0]);

    // stop timer
    end_tick = rdtsc();
    #ifdef DEBUG
    fprintf(stderr, "End tick is %llu\n", end_tick);
    fflush(stderr);
    #endif

    // print time
    double time_duration = (double)(end_tick - begin_tick) / (double)curr_CPU_freq;
    printf("%lf\n", time_duration);
    fflush(stdout);

    // exit child process
    _exit(0);
  }
  else
  {
    // Parent Process
    // wait to receive msg from child
    #ifdef DEBUG
    fprintf(stderr, "Parent Reading...\n");
    fflush(stderr);
    #endif
    // read pipe from child
    close(pipe_ctp[1]);
    while(read(pipe_ctp[0], &buf, 1) > 0)
    {
      // write message to stdout
      #ifdef DEBUG
      fprintf(stderr, "%c", buf);
      fflush(stderr);
      #endif
    }
    #ifdef DEBUG
    fprintf(stderr, "\n");
    fflush(stderr);
    #endif
    close(pipe_ctp[0]);

    // send 1-word msg back to child
    #ifdef DEBUG
    fprintf(stderr, "Parent sending...\n");
    fflush(stderr);
    #endif
    // close unused read end
    close(pipe_ptc[0]);
    write(pipe_ptc[1], msg1, 4);
    // close write after msg sending
    close(pipe_ptc[1]);
    
    // wait for child to terminate
    wait(NULL);
    // exit parent process
    exit(0);
  }
}
